package com.sc.web.servlet;

import com.sc.web.gwt.server.hotpgenerator.OneTimePassword;
import com.sc.web.gwt.server.persistence.AuthenticatorPersistence;
import com.sc.web.gwt.server.persistence.UserAccountPersistence;
import com.sc.web.gwt.server.util.SeedGenerator;
import com.sc.web.gwt.shared.model.Authenticator;
import com.sc.web.gwt.shared.model.UserAccount;

import javax.jws.WebMethod;
import javax.jws.WebService;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * User: KienCT
 * Date: 26/07/2011
 * Time: 16:23
 */
@WebService()
public class AuthenticatorService {
    private final AuthenticatorPersistence authenticatorPersistence = new AuthenticatorPersistence();
    private final UserAccountPersistence userAccountPersistence = new UserAccountPersistence();

    @WebMethod
    public String sayHelloWorldFrom(String from) {
        String result = "Hello, world, from " + from;
        System.out.println(result);
        return result;
    }

    @WebMethod
    public String initAuthenticator(String secretKey, String accountCode) {
        if (secretKey == null || secretKey.equals("") || accountCode == null || accountCode.equals("")) {
            return "";
        }

        Authenticator authenticator = new Authenticator();
        authenticator.setSeed(SeedGenerator.getSeed());
        authenticator.setSecretKey(secretKey);
        authenticator.setEvent("0");
        authenticatorPersistence.insertAuthenticator(authenticator);

        boolean result = userAccountPersistence.activateAccount(accountCode, authenticatorPersistence.getAuthenticatorBySeed(authenticator.getSeed()).getAuthenticatorId());
        if (result) {
            return authenticator.getSeed();
        }

        return "";
    }

    @WebMethod
    public String syncAuthenticator(String secretKey, String seed, String event) {
        if (seed != null && !seed.equals("") && event != null && !event.equals("") && secretKey != null && !secretKey.equals("")) {
            if (authenticatorPersistence.syncAuthenticatorEvent(seed, event, secretKey)) {
                return "true";
            }
        }
        return "false";
    }

    @WebMethod
    public String attachAuthenticator(String accountCode, String seed) {
        if (seed == null || seed.equals("") || accountCode == null || accountCode.equals("")) {
            return "";
        }
        Authenticator authenticator = authenticatorPersistence.getAuthenticatorBySeed(seed);
        UserAccountPersistence userAccountPersistence = new UserAccountPersistence();
        if (userAccountPersistence.activateAccount(accountCode, authenticator.getAuthenticatorId())) {
            return "true";
        }

        return "false";
    }

    @WebMethod
    public boolean changeSecretKey(String secretKey, String seed) {
        boolean result = false;

        if (seed != null && !seed.equals("") && secretKey != null && !secretKey.equals("")) {
            result = authenticatorPersistence.changeSecretKey(seed, secretKey);
        }

        return result;
    }

    /**
     * END USER LOGIN SERVICE, use HOTP code
     *
     * @param userName end-user account name
     * @param password HOTP
     * @return whether or not user login successfully
     */
    @WebMethod
    public boolean loginService(String userName, String password) throws InvalidKeyException, NoSuchAlgorithmException {
        UserAccount userAccount = userAccountPersistence.getUserAccountDataByAccountName(userName);

        if (userAccount == null) {
            return false;
        }

        String seed = userAccount.getSeed();

        Authenticator authenticator = authenticatorPersistence.getAuthenticatorBySeed(seed);

        String secretKey = authenticator.getSecretKey();
        String event = authenticator.getEvent();
        String temp = secretKey + seed;

        String generatedCode;

        for (int i = 0; i < 10; i++) {
            generatedCode = OneTimePassword.generateOTP(temp.getBytes(), Long.parseLong(event) + i, 6, false, 5);
            if (generatedCode.equals(password)) {
                authenticator.setEvent(String.valueOf((Long.parseLong(event) + i + 1)));
                authenticatorPersistence.updateAuthenticator(authenticator);
                return true;
            }
        }

        return false;
    }
}